package com.papper.mng.controller.sys;

import com.github.pagehelper.PageInfo;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.papper.common.annotation.PapperLog;
import com.papper.common.bean.sys.SysGroup;
import com.papper.common.bean.sys.SysLimit;
import com.papper.common.bean.sys.SysModel;
import com.papper.common.bean.sys.SysResource;
import com.papper.common.bean.sys.SysSystem;
import com.papper.common.bean.sys.SysUser;
import com.papper.common.config.SysCodeHelp;
import com.papper.common.constant.SystemConstants;
import com.papper.common.enums.DataStatusEnum;
import com.papper.common.enums.LimitTypeEnum;
import com.papper.common.exception.ServiceException;
import com.papper.common.service.DwzPage;
import com.papper.common.service.log.LogEmailService;
import com.papper.common.service.sys.SysGroupService;
import com.papper.common.service.sys.SysLimitService;
import com.papper.common.service.sys.SysModelService;
import com.papper.common.service.sys.SysResourceService;
import com.papper.common.service.sys.SysSystemService;
import com.papper.common.service.sys.SysUserService;
import com.papper.common.utils.encrypt.Md5Tool;
import com.papper.common.utils.tool.OrderTool;
import com.papper.common.utils.tool.StringTool;
import com.papper.mng.controller.BaseAction;
import com.papper.mng.domain.DwzResponse;
import com.papper.mng.utils.tool.GoogleAuthenticator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.util.StringUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author:Lajiao
 * @Date:2014年8月21日
 * @Time:下午12:42:13
 * @Description:用户信息
 */
@Controller
@RequestMapping("/sys/user")
public class SysUserAction extends BaseAction {
    @Autowired
    SysGroupService    sysGroupService;
    @Autowired
    SysResourceService sysResourceService;
    @Autowired
    SysUserService     sysUserService;
    @Autowired
    SysLimitService    sysLimitService;
    @Autowired
    SysSystemService   sysSystemService;
    @Autowired
    SysModelService    sysModelService;
    @Autowired
    LogEmailService    logEmailService;

    /**
     * 用户信息
     *
     * @return
     */
    @GetMapping(value = "")
    public String execute(HttpServletRequest _request, Model model, Long sid, Long gid, String filterValue) {
        // 所属系统
        List<SysSystem> systems = sysSystemService.findAll();
        model.addAttribute("systems", systems);
        SysSystem sysSystem = sysSystemService.findById(sid);
        if (sysSystem == null && systems.size() > 0) {
            sysSystem = systems.get(0);
        }
        if (sysSystem == null) {
            return render("sys/user/index");
        }
        // 所属角色
        SysUser sessionUser = getLoginUser();
        model.addAttribute("sysSystem", sysSystem);
        model.addAttribute("sid", sysSystem.getId());
        List<SysGroup> sysGroups = sysGroupService.findByUserId(sysSystem.getId().toString(), sessionUser.getId().toString());
        if (sysGroups == null) {
            return render("sys/user/index");
        }
        SysGroup sysGroup = sysGroupService.findById(gid);
        if (sysGroup == null && sysGroups.size() > 0) {
            sysGroup = sysGroups.get(0);
        } else if (sysGroup != null && sysGroup.getSystemId() != sysSystem.getId().intValue()) {
            sysGroup = sysGroups.get(0);
        }
        if (sysGroup == null) {
            return render("sys/user/index");
        }
        // 所属用户
        model.addAttribute("sysGroups", sysGroups);
        model.addAttribute("sysGroup", sysGroup);
        model.addAttribute("gid", sysGroup.getId());
        model.addAttribute("filterValue", filterValue);
        // 获取用户信息
        // 字段查询条件
        Map<String, Object> objects = Maps.newHashMap();
        baseParams(objects, request(), SysUser.class);
        Example          example  = new Example(SysUser.class);
        Example.Criteria criteria = example.createCriteria().andAllEqualTo(objects);

        extraParams(objects, _request, SysUser.class);
        objects.put("filterValue", filterValue);
        objects.put("groupId", sysGroup.getId());
        criteria.andEqualTo("groupId", sysGroup.getId());
        if (!StringUtil.isEmpty(filterValue)) {
            criteria.andLike("loginName", "%" + filterValue + "%");
        }
        modelParm(objects, model);
        // 分页查询条件
        int pageNum    = StringTool.parseInteger(_request.getParameter("pageNum"), 1);
        int numPerPage = StringTool.parseInteger(_request.getParameter("numPerPage"), SystemConstants.PAGE_LIMIT_16);
        // 数据查询
        PageInfo<SysUser> pageRtn = sysUserService.findPage(pageNum, numPerPage, example);
        model.addAttribute("page", new DwzPage(pageNum, numPerPage, pageRtn.getTotal()));
        model.addAttribute("records", pageRtn.getList());

        return render("sys/user/index");
    }

    @GetMapping(value = "/add")
    public String add_get(Model model, Long sid, Long gid) {
        SysSystem sysSystem = sysSystemService.findById(sid);
        model.addAttribute("sid", sid);
        model.addAttribute("sysSystem", sysSystem);
        SysGroup sysGroup = sysGroupService.findById(gid);
        model.addAttribute("gid", gid);
        model.addAttribute("sysGroup", sysGroup);
        model.addAttribute("nick", getNick());
        return render("sys/user/add");
    }

    @PostMapping(value = "/add")
    @ResponseBody
    public DwzResponse add_post(HttpServletRequest _request, Long gid, SysUser sysUser) {
        try {
            checkSuperCert(_request);
        } catch (ServiceException e) {
            return new DwzResponse("300", e.getMessage());
        }
        SysGroup sysGroup = sysGroupService.findById(gid);
        if (sysGroup == null) {
            return new DwzResponse("300", "参数[gid]信息异常！");
        }
        SysUser sessionUser = getLoginUser();
        if (sessionUser == null) {
            return new DwzResponse("300", "登录用户信息异常！");
        }
        String loginPass = OrderTool.getRandomPass(6);
        sysUser.setSystemId(sysGroup.getSystemId());
        sysUser.setLoginPass(Md5Tool.getMd5(loginPass));
        sysUser.setGroupId(sysGroup.getId().intValue());
        sysUser.setParentId(sessionUser.getId().intValue());
        sysUser.setDataStatus(DataStatusEnum.OPEN.getCode());
        sysUser.setLimitType(LimitTypeEnum.GROUP.getCode());
        sysUser.setUserChild(0);
        sysUser.setFamily("");
        // 添加角色信息
        try {
            sysUser.setCreateTime(new Date());
            sysUser.setModifyTime(new Date());
            sysUserService.save(sysUser);
        } catch (Exception e) {
            e.printStackTrace();
            return new DwzResponse("300", "用户添加失败:" + e.getMessage() + "!!!");
        }
        // 维护组树信息
        sysUserService.matchFamily(sysUser);
        sysUserService.matchChild(sysUserService.findById(sessionUser.getId().intValue()));
        // 推送密码重置邮件
        StringBuffer content = new StringBuffer();
        content.append("访问地址:").append(":[");
        SysSystem sysSystem = sysSystemService.findById(sysGroup.getSystemId());
        content.append(sysSystem.getSystemUrl());
        content.append("]");
        content.append("登录账户:").append(":[");
        content.append(sysUser.getLoginName());
        content.append("]");
        content.append("登录密码:").append(":[");
        content.append(loginPass);
        content.append("],请妥善保管您的账号密码");
        String from = SysCodeHelp.I().TGS("SysMailSendConfig", "mail.default.from", null);
        logEmailService.sendEmail(from, sysUser.getUserEmail(), "账户信息添加成功", content.toString(), null);
        return new DwzResponse("200", "用户添加成功!!!");
    }

    /**
     * 用户信息_更新
     *
     * @param _response
     * @param id
     * @throws IOException
     */
    @GetMapping(value = "/edit")
    public String edti_get(HttpServletResponse _response, Model model, Long id) {
        SysUser entity = sysUserService.findById(id);
        model.addAttribute("entity", entity);
        SysSystem sysSystem = sysSystemService.findById(entity.getSystemId());
        model.addAttribute("sid", entity.getSystemId());
        model.addAttribute("sysSystem", sysSystem);
        SysGroup sysGroup = sysGroupService.findById(entity.getGroupId());
        model.addAttribute("gid", entity.getGroupId());
        model.addAttribute("sysGroup", sysGroup);
        model.addAttribute("nick", getNick());
        return render("sys/user/edit");
    }

    @PostMapping(value = "/edit")
    @ResponseBody
    public DwzResponse edit_post(HttpServletRequest _request, SysUser sysUser) {
        try {
            checkSuperCert(_request);
        } catch (ServiceException e) {
            return new DwzResponse("300", e.getMessage());
        }

        SysUser sessionUser = getLoginUser();
        if (sysUser == null || sysUser.getId() == null) {
            return new DwzResponse("300", "参数[sysUser]异常！");
        }

        SysUser old = sysUserService.findById(sysUser.getId());
        if (old != null && !old.getFamily().startsWith(sessionUser.getFamily())) {
            return new DwzResponse("300", "您没有权限修改该用户信息！");
        }

        try {
            sysUser.setModifyTime(new Date());
            sysUserService.update(sysUser);
            return new DwzResponse("200", "用户信息修改成功!!!");
        } catch (Exception e) {
            e.printStackTrace();
            return new DwzResponse("300", "用户信息修改失败:" + e.getMessage());
        }
    }

    /**
     * 角色信息_删除
     *
     * @param id
     * @throws IOException
     */
    @PostMapping(value = "/del")
    @ResponseBody
    public DwzResponse del_post(HttpServletRequest _request, Long id) {
        try {
            checkSuperCert(_request);
        } catch (ServiceException e) {
            return new DwzResponse("300", e.getMessage());
        }

        if (id == null || id.intValue() <= 0) {
            return new DwzResponse("300", "参数异常！");
        }

        SysUser sessionUser = getLoginUser();
        SysUser old         = sysUserService.findById(id);
        if (old != null && old.getParentId().intValue() != sessionUser.getId().intValue()) {
            return new DwzResponse("300", "您没有权限删除该用户信息！");
        }

        try {
            sysUserService.deleteById(id);
            sysUserService.matchChild(sysUserService.findById(old.getParentId()));
            return new DwzResponse("200", "用户信息删除成功!!!");
        } catch (Exception e) {
            e.printStackTrace();
            return new DwzResponse("300", "系统错误,请稍候再试!!![" + e.getMessage() + "]");
        }
    }

    /**
     * 用户信息_权限设置
     *
     * @param uid
     * @throws IOException
     */
    @GetMapping(value = "/limit")
    public String limit_get(Model model, Long uid) {
        SysUser dbUser = sysUserService.findById(uid);
        if (dbUser == null) {
            return render("sys/user/limit");
        }
        // 获取用户所属系统
        SysGroup sysGroup = sysGroupService.findById(dbUser.getGroupId());
        if (sysGroup == null) {
            return render("sys/user/limit");
        }
        // 获取系统信息
        SysSystem sysSystem = sysSystemService.findById(sysGroup.getSystemId());
        if (sysSystem == null) {
            return render("sys/user/limit");
        }
        model.addAttribute("sysUser", dbUser);
        model.addAttribute("sysGroup", sysGroup);
        model.addAttribute("sysSystem", sysSystem);
        SysUser sysUser = getLoginUser();
        // 获取用户模块一览
        List<SysModel> sysModels = sysModelService.findByLimit(sysSystem.getId(), sysUser);
        model.addAttribute("sysModels", sysModels);
        // 获取用户权限一览
        List<SysResource> resources = sysResourceService.findLimitBySystemId(sysSystem.getId(), sysUser);
        // 获取组权限一览
        List<SysLimit>        limits       = sysLimitService.getUserLimits(LimitTypeEnum.USER.getCode(), dbUser.getId());
        Map<Integer, Integer> oldUserLimit = Maps.newHashMap();
        if (limits != null) {
            for (SysLimit sysLimit : limits) {
                oldUserLimit.put(sysLimit.getResId(), sysLimit.getLimitValue());
            }
        }
        // 组装数据
        List<SysResource>            temp          = null;
        Map<Long, List<SysResource>> modelResource = Maps.newLinkedHashMap();
        for (SysResource sysResource : resources) {
            if (oldUserLimit.get(sysResource.getId().intValue()) != null) {
                sysResource.setLimitValue(oldUserLimit.get(sysResource.getId().intValue()));
            }
            temp = modelResource.get(sysResource.getModelId().longValue());
            if (temp == null) {
                temp = Lists.newArrayList();
            }
            temp.add(sysResource);
            modelResource.put(sysResource.getModelId().longValue(), temp);
        }
        for (Long rid : modelResource.keySet()) {
            modelResource.put(rid, sysResourceService.treeChildList(modelResource.get(rid)));
        }
        model.addAttribute("modelResource", modelResource);
        return render("sys/user/limit");
    }

    @PostMapping(value = "/limit")
    @ResponseBody
    public DwzResponse limit_post(HttpServletRequest _request, String userId, String limits) {
        try {
            checkSuperCert(_request);
        } catch (ServiceException e) {
            return new DwzResponse("300", e.getMessage());
        }
        if (StringUtil.isEmpty(userId)) {
            return new DwzResponse("300", "参数[uid]为空！");
        }
        SysUser sysUser = sysUserService.findById(userId);
        if (sysUser == null) {
            return new DwzResponse("300", "参数[gid]信息异常！");
        }
        SysUser sessionUser = getLoginUser();
        if (!isSuperUser() && !sysUser.getFamily().startsWith(sessionUser.getFamily())) {
            return new DwzResponse("300", "您无权限操作该用户！");
        }
        // 权限设置
        List<SysLimit> modifyLimits = Lists.newArrayList();
        SysLimit       sysLimit;
        List<String>   ids          = Splitter.on(',').trimResults().omitEmptyStrings().splitToList(limits);
        if (ids != null) {
            for (String id : ids) {
                if (StringTool.parseInteger(id, 0) <= 0) {
                    continue;
                }
                sysLimit = new SysLimit();
                sysLimit.setLimitType(LimitTypeEnum.USER.getCode());
                sysLimit.setLimitId(StringTool.parseInteger(userId, null));
                sysLimit.setResId(StringTool.parseInteger(id, null));
                sysLimit.setLimitValue(1);
                modifyLimits.add(sysLimit);
            }
        }
        try {
            // 清空权限信息
            sysLimitService.delLimitedByUserIds(userId);
            // 添加新权限信息
            sysLimitService.batchInsert(modifyLimits);
            if (modifyLimits.size() > 0) {
                sysUserService.updateLimitType(sysUser.getId(), LimitTypeEnum.USER.getCode());
            } else {
                sysUserService.updateLimitType(sysUser.getId(), LimitTypeEnum.GROUP.getCode());
            }
            return new DwzResponse("200", "权限保存成功!!!");
        } catch (Exception e) {
            e.printStackTrace();
            return new DwzResponse("300", "系统错误,请稍候再试!!![" + e.getMessage() + "]");
        }
    }

    /**
     * 用户信息_详情
     *
     * @return
     */
    @GetMapping(value = "/detail")
    public String detail(Model model, Long id) {
        SysUser sysUser     = sysUserService.findById(id);
        SysUser sessionUser = getLoginUser();
        if (sysUser != null && !sysUser.getFamily().startsWith(sessionUser.getFamily())) {
            model.addAttribute("entity", null);
        } else {
            model.addAttribute("entity", sysUser);
            SysSystem sysSystem = sysSystemService.findById(sysUser.getSystemId());
            model.addAttribute("sid", sysUser.getSystemId());
            model.addAttribute("sysSystem", sysSystem);
            SysGroup sysGroup = sysGroupService.findById(sysUser.getGroupId());
            model.addAttribute("gid", sysUser.getGroupId());
            model.addAttribute("sysGroup", sysGroup);
            model.addAttribute("nick", getNick());
            
            String qrcode = GoogleAuthenticator.getQRBarcodeURL(sysUser.getId().toString(), sysSystem.getSystemHost(), sysUser.getKeyCode());
            model.addAttribute("getQRBarcodeURL", qrcode);
        }
        return render("sys/user/detail");
    }

    /**
     * 密码重置
     *
     * @param _request
     * @throws IOException
     */
    @PostMapping(value = "/passreset")
    @ResponseBody
    public DwzResponse passreset_post(HttpServletRequest _request) {
        try {
            checkSuperCert(_request);
        } catch (ServiceException e) {
            return new DwzResponse("300", e.getMessage());
        }
        SysUser sysUser = getLoginUser();
        String  id      = _request.getParameter("id");
        SysUser dbUser  = sysUserService.findById(id);
        if (dbUser == null) {
            return new DwzResponse("300", "该用户信息不存在!!!");
        }
        if (dbUser.getParentId().intValue() != sysUser.getId().intValue()) {
            return new DwzResponse("300", "您无权限重置该账户密码!!!");
        }
        String defaultPass = OrderTool.getRandomPass(6);
        try {
            dbUser.setLoginPass(Md5Tool.getMd5(defaultPass));
            sysUserService.update(dbUser);
        } catch (Exception e) {
            return new DwzResponse("300", "密码重置失败:" + e.getMessage() + "!!!");
        }
        // 推送密码重置邮件
        StringBuffer content = new StringBuffer();
        content.append("访问地址:").append(":[");
        SysSystem sysSystem = sysSystemService.findById(dbUser.getSystemId());
        content.append(sysSystem.getSystemUrl());
        content.append("]");
        content.append("登录账户:").append(":[");
        content.append(dbUser.getLoginName());
        content.append("]");
        content.append("新密码").append(":[");
        content.append(defaultPass);
        content.append("],请妥善保管您的账号密码");
        String from = SysCodeHelp.I().TGS("SysMailSendConfig", "mail.default.from", null);
        logEmailService.sendEmail(from, dbUser.getUserEmail(), "密码重置成功", content.toString(), null);
        return new DwzResponse("200", "密码重置成功!!!");
    }

    /**
     * 用户信息_谷歌验证码
     *
     * @param id
     * @throws IOException
     */
    @GetMapping(value = "/google")
    public String google_get(Model model, Long id) {
        SysUser entity = sysUserService.findById(id);
        model.addAttribute("entity", entity);

        SysSystem sysSystem = sysSystemService.findById(entity.getSystemId());
        model.addAttribute("sid", entity.getSystemId());
        model.addAttribute("sysSystem", sysSystem);
        SysGroup sysGroup = sysGroupService.findById(entity.getGroupId());
        model.addAttribute("gid", entity.getGroupId());
        model.addAttribute("sysGroup", sysGroup);
        model.addAttribute("nick", getNick());

        String secret = GoogleAuthenticator.generateSecretKey();
        model.addAttribute("generateSecretKey", secret);
        String qrcode = GoogleAuthenticator.getQRBarcodeURL(entity.getId().toString(), sysSystem.getSystemHost(), secret);
        model.addAttribute("getQRBarcodeURL", qrcode);

        return render("sys/user/google");
    }

    @PapperLog(detail = "用户谷歌授权码:[{{user}}]")
    @PostMapping(value = "/google")
    @ResponseBody
    public DwzResponse google_post(HttpServletRequest _request, SysUser sysUser) {
        try {
            checkVerifyCert(_request);
        } catch (ServiceException e) {
            return new DwzResponse("300", e.getMessage());
        }
        try {
            sysUserService.update(sysUser);
            return new DwzResponse("200", "用户信息修改成功!!!");
        } catch (Exception e) {
            e.printStackTrace();
            return new DwzResponse("300", "用户信息修改失败:" + e.getMessage());
        }
    }
}
